#include "stdafx.h"
#include "DnsQuery.h"

using namespace Adaptive::Network::Dns;
using namespace System::Text;

DnsQuery::DnsQuery()
{
}

array<ManagedDnsRecord^>^ DnsQuery::PerformDnsQuery(String^ addressOrDomainName, DnsQueryType queryType, DnsQueryOption options)
{
	array<ManagedDnsRecord^>^	returnValue = nullptr;
	CString						wideName = addressOrDomainName;
	DNS_STATUS					result = 0;
	DNS_RECORD*					itemPtr = NULL;
	DNS_RECORD*					recordList = NULL;
	int count = 0;
	int length = 0;
	IPAddress^ ipAddress = nullptr;

	//Perform the query.
	try
	{
		ipAddress = IPAddress::Parse(addressOrDomainName);
	}
	catch(...)
	{
		ipAddress = nullptr;
	}

	if (ipAddress != nullptr)
	{
		addressOrDomainName = DnsQuery::TransformForReverseIp(ipAddress);
		wideName = addressOrDomainName;
	}

	result = ::DnsQuery_W(wideName, (WORD)queryType, (DWORD)options, NULL, &recordList, NULL);
	if (result == (DWORD)ERROR_SUCCESS)
	{
		//Count the records.
		itemPtr = recordList;
		while (itemPtr != NULL)
		{
			length++;
			itemPtr = itemPtr->pNext;
		}

		//Create the array and managed objects.
		returnValue = gcnew array<ManagedDnsRecord^>(length);
		while (recordList != NULL)
		{
			returnValue[count] = gcnew ManagedDnsRecord(recordList);
			count++;
			recordList = recordList->pNext;
		};

		//Clear memory.
		itemPtr = NULL;
		::DnsRecordListFree(recordList, ::DnsFreeRecordListDeep);
		recordList = NULL;
	}
	return returnValue;
}

String^ DnsQuery::TransformForReverseIp(IPAddress^ original)
{
	String^ returnValue = nullptr;
	StringBuilder^ builder = nullptr;
	array<Byte>^ bytes = original->GetAddressBytes();

	builder = gcnew StringBuilder();
	builder->Append(bytes[3].ToString());
	builder->Append(".");
	builder->Append(bytes[2].ToString());
	builder->Append(".");
	builder->Append(bytes[1].ToString());
	builder->Append(".");
	builder->Append(bytes[0].ToString());
	builder->Append(".");
	builder->Append("IN-ADDR.ARPA");

	returnValue = builder->ToString();
	delete(builder);
	delete(bytes);
	return returnValue;
}
